﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using FireStarter.CodeGeneration;
using FireStarterModeller.BO;
using Habanero.BO;

namespace FireStarterModeller.UI.CodeGeneration
{
    public class CodeGenerationController : ICodeGenerationController
    {
        public GenerationSettings GenerationSettings { get; private set; }

        public CodeGenerationController(GenerationSettings generationSettings)
        {
            if (generationSettings == null) throw new ArgumentNullException("generationSettings");
            GenerationSettings = generationSettings;
            generationSettings.Relationships.GetSingle("SolutionType").RelatedBusinessObjectChanged += GenerationSettings_OnSolutionTypeChanged;
        }

        public BusinessObjectCollection<SolutionType> GenerateDefaultSolutionTypes()
        {
            GenerateDefaultProjectTypes();
            SolutionType solutionTypeWinForms = CreateSolutionType(GenerationTypes.SOLUTION_TYPE_WIN);
            SolutionType solutionTypeWebGui = CreateSolutionType(GenerationTypes.SOLUTION_TYPE_VWG);
            SolutionType solutionTypeDualWinFormWebGui = CreateSolutionType(GenerationTypes.SOLUTION_TYPE_DUALWINVWG);

            LinkSolutionTypeToProjectType(solutionTypeWinForms, GenerationTypes.PROJECT_TYPE_MAIN_WIN);
            LinkSolutionTypeToProjectType(solutionTypeWinForms, GenerationTypes.PROJECT_TYPE_BO);
            LinkSolutionTypeToProjectType(solutionTypeWinForms, GenerationTypes.PROJECT_TYPE_LOGIC);
            LinkSolutionTypeToProjectType(solutionTypeWinForms, GenerationTypes.PROJECT_TYPE_UI_WIN);
            LinkSolutionTypeToProjectType(solutionTypeWinForms, GenerationTypes.PROJECT_TYPE_TEST_BASE);
            LinkSolutionTypeToProjectType(solutionTypeWinForms, GenerationTypes.PROJECT_TYPE_TEST_BO);
            LinkSolutionTypeToProjectType(solutionTypeWinForms, GenerationTypes.PROJECT_TYPE_TEST_LOGIC);
            LinkSolutionTypeToProjectType(solutionTypeWinForms, GenerationTypes.PROJECT_TYPE_TEST_UI);

            LinkSolutionTypeToProjectType(solutionTypeWebGui, GenerationTypes.PROJECT_TYPE_MAIN_VWG);
            LinkSolutionTypeToProjectType(solutionTypeWebGui, GenerationTypes.PROJECT_TYPE_BO);
            LinkSolutionTypeToProjectType(solutionTypeWebGui, GenerationTypes.PROJECT_TYPE_LOGIC);
            LinkSolutionTypeToProjectType(solutionTypeWebGui, GenerationTypes.PROJECT_TYPE_UI_VWG);
            LinkSolutionTypeToProjectType(solutionTypeWebGui, GenerationTypes.PROJECT_TYPE_TEST_BASE);
            LinkSolutionTypeToProjectType(solutionTypeWebGui, GenerationTypes.PROJECT_TYPE_TEST_BO);
            LinkSolutionTypeToProjectType(solutionTypeWebGui, GenerationTypes.PROJECT_TYPE_TEST_LOGIC);
            LinkSolutionTypeToProjectType(solutionTypeWebGui, GenerationTypes.PROJECT_TYPE_TEST_UI);

            LinkSolutionTypeToProjectType(solutionTypeDualWinFormWebGui, GenerationTypes.PROJECT_TYPE_MAIN_VWG);
            LinkSolutionTypeToProjectType(solutionTypeDualWinFormWebGui, GenerationTypes.PROJECT_TYPE_MAIN_WIN);
            LinkSolutionTypeToProjectType(solutionTypeDualWinFormWebGui, GenerationTypes.PROJECT_TYPE_BO);
            LinkSolutionTypeToProjectType(solutionTypeDualWinFormWebGui, GenerationTypes.PROJECT_TYPE_LOGIC);
            LinkSolutionTypeToProjectType(solutionTypeDualWinFormWebGui, GenerationTypes.PROJECT_TYPE_UI_BASE);
            LinkSolutionTypeToProjectType(solutionTypeDualWinFormWebGui, GenerationTypes.PROJECT_TYPE_UI_VWG);
            LinkSolutionTypeToProjectType(solutionTypeDualWinFormWebGui, GenerationTypes.PROJECT_TYPE_UI_WIN);
            LinkSolutionTypeToProjectType(solutionTypeDualWinFormWebGui, GenerationTypes.PROJECT_TYPE_TEST_BASE);
            LinkSolutionTypeToProjectType(solutionTypeDualWinFormWebGui, GenerationTypes.PROJECT_TYPE_TEST_BO);
            LinkSolutionTypeToProjectType(solutionTypeDualWinFormWebGui, GenerationTypes.PROJECT_TYPE_TEST_LOGIC);
            LinkSolutionTypeToProjectType(solutionTypeDualWinFormWebGui, GenerationTypes.PROJECT_TYPE_TEST_UI);
            BusinessObjectCollection<SolutionType> solutionTypes = new BusinessObjectCollection<SolutionType>();
            solutionTypes.Add(solutionTypeWinForms, solutionTypeWebGui, solutionTypeDualWinFormWebGui);
            return solutionTypes.GetSortedCollection("Name", true);
        }

        private static SolutionType CreateSolutionType(string solutionTypeName)
        {
            SolutionType solutionType = new SolutionType();
            solutionType.Name = solutionTypeName;
            solutionType.Save();
            return solutionType;
        }

        private static void GenerateDefaultProjectTypes()
        {
            CreateProjectType(GenerationTypes.PROJECT_TYPE_MAIN_VWG);
            CreateProjectType(GenerationTypes.PROJECT_TYPE_MAIN_WIN);
            CreateProjectType(GenerationTypes.PROJECT_TYPE_BO);
            CreateProjectType(GenerationTypes.PROJECT_TYPE_LOGIC);
            //CreateProjectType(GenerationTypes.PROJECT_TYPE_UI);
            CreateProjectType(GenerationTypes.PROJECT_TYPE_UI_BASE);
            CreateProjectType(GenerationTypes.PROJECT_TYPE_UI_WIN);
            CreateProjectType(GenerationTypes.PROJECT_TYPE_UI_VWG);
            CreateProjectType(GenerationTypes.PROJECT_TYPE_TEST_BASE);
            CreateProjectType(GenerationTypes.PROJECT_TYPE_TEST_BO);
            CreateProjectType(GenerationTypes.PROJECT_TYPE_TEST_LOGIC);
            CreateProjectType(GenerationTypes.PROJECT_TYPE_TEST_UI);
        }

        private static void CreateProjectType(string typeName)
        {
            ProjectType projectType = new ProjectType();
            projectType.Name = typeName;
            projectType.Save();
        }

        private static void LinkSolutionTypeToProjectType(SolutionType solutionTypeWinForms, string projectTypeName)
        {
            SolutionTypeProject solutionTypeProject = solutionTypeWinForms.SolutionTypeProjects.CreateBusinessObject();
            string criteria = String.Format("Name='{0}'", projectTypeName);
            solutionTypeProject.ProjectType = Broker.GetBusinessObject<ProjectType>(criteria);
            solutionTypeProject.Save();
        }

        private void GenerationSettings_OnSolutionTypeChanged(object sender, EventArgs e)
        {
            foreach (ProjectTypeGeneration projectTypeGeneration in GenerationSettings.ProjectTypeGenerations.ToArray())
            {
                projectTypeGeneration.MarkForDelete();
            }

            SolutionType solutionType = GenerationSettings.SolutionType;
            if (solutionType != null)
            {
                foreach (SolutionTypeProject solutionTypeProject in solutionType.SolutionTypeProjects)
                {
                    ProjectTypeGeneration projectTypeGeneration = GenerationSettings.ProjectTypeGenerations.CreateBusinessObject();
                    projectTypeGeneration.ProjectType = solutionTypeProject.ProjectType;
                    if (projectTypeGeneration.ProjectType.Name.ToUpper().Contains("TEST"))
                    {
                        projectTypeGeneration.ToBeGenerated = false;
                    }

                    AutoGenerateProjectName(projectTypeGeneration);
                }
            }
        }

        public void AutoGenerateProjectName(ProjectTypeGeneration projectTypeGeneration)
        {
            //TODO Mark 14 Oct 2009: This should be changed to use a naming template that is in the ProjectType. eg. "{SolutionName}.BO"
            string solutionTypeName = GenerationSettings.SolutionType.Name;
            string solutionName = GenerationSettings.SolutionName;
            string projectTypeName = projectTypeGeneration.ProjectType.Name;

            string projectName = MasterGenerator.GetSuitableProjectName(solutionName, projectTypeName, solutionTypeName);
            projectTypeGeneration.ProjectName = projectName;

            //string projectTypeName = projectTypeGeneration.ProjectType.Name;
            //if (projectTypeName == GenerationTypes.PROJECT_TYPE_MAIN_VWG || projectTypeName == GenerationTypes.PROJECT_TYPE_MAIN_WIN)
            //{
            //    projectTypeGeneration.ProjectName = _dmSolution.GenerationSettings.SolutionName;
            //}
            //else
            //{
            //    projectTypeGeneration.ProjectName = _dmSolution.GenerationSettings.SolutionName + "." +
            //                                        projectTypeName;
            //}
        }

        public BusinessObjectCollection<SolutionType> LoadSolutionTypes()
        {
            BusinessObjectCollection<SolutionType> solutionTypes = Broker.GetBusinessObjectCollection<SolutionType>("", "Name");
            if (solutionTypes.Count != 0) return solutionTypes;
            return GenerateDefaultSolutionTypes();
        }
    }
}
